/******************************************************************************
 * class represents an outer surface in a simulation unit, such as wall, floor or roof
 * beregning av varmetap gjennom vegger skal utføres med hensyn til yttreflater
 * som har forskjellig temperatur på ytterside og inne.
 ******************************************************************************/

package simulator.engine;



import interfaces.HeatLoss;
import java.util.ArrayList;


/**
 * 
 * @author 490501
 * @version 1.0.1
 * 
 * OBS! alle tall gitt i: 
 * lengde - mm; 
 * U verdi - W/m^2*K;
 * temperature Celsius grader eller Kelvin;
 * area in m^2;
 */
public class Surface implements HeatLoss{
    
    /**
     * width of surface in mm<
     */
    private double dimX; 

    /**
     * height of surface in mm
     */
    private double dimY; 
    
    /**
     * square of entity in m^2
     * (dimX * dimY) / 1 000 000
     */
    private double square;  

    /**
     * Overall heat transfer coefficient W/m^2*K
     */
    private double uValue;
    
    /**
     * Kuldebroverdi
     * (not used)
     */
    private double thermalBridgeValue;

    /**
     * orientation of surface
     * s - south, n - norh, w - west, e - east
     */
    private char orientation;
    
    /**
     * difference between tempereture innside and outside grades Celsius or Kelvin
     */
    private double tempDifference;
    
    /**
     * differences between tempereture innside and outside grades Celsius
     * 
     */
    @Deprecated
    private double[] tempDifferences;
    
    /**
     * uses if surface represents wall with windows, or roof with windows
     * hver enkel vindu representeres akkurat på det samme måte som vegg
     */
    private ArrayList<Surface> child; 
    /**************************************************************************/
    /*Constructors area*/ 
     
    /**
     * empty constructor
     */
    public Surface() { 
    }
    /**
     * constructor
     * @param dimX width of surface in mm
     * @param dimY high of surface in mm
     * @param uValue U-value
     */
    public Surface(double dimX, double dimY, double uValue) {
        this.dimX = dimX; //mm
        this.dimY = dimY; //mm
        this.square = (this.dimX*this.dimY)/1000000; //m^2
        this.uValue = uValue;//1 watt per m^2*K 
    } 
/******************************************************************************/
    //End of constructors area

/******************************************************************************/
    //functions 
    
    /**
     * @param dimXint width of surface in mm
     * @param dimYint high of surface in mm
     * @param uValue  verall heat transfer coefficient
     * @throws OversizedException if size of child more than surface size
     */
    public void addChild(double dimXint, double dimYint, double uValue) throws Exception{
        if(this.child == null) {
            this.child = new ArrayList<Surface>();
        }
        if(this.square < dimXint*dimYint+this.countSquareOfChildren()) {
            throw new Exception("square of window(s) more than square of wall");
        }
        this.child.add(new Surface(dimXint, dimYint,uValue));
    }
    
    /**
     * 
     * @param i position of window which had to be removed in windows arraylist
     */
    public void removeChild(int i) {
        this.child.remove(i);
    }
    
    /**
     * 
     * @param s window which had to be removed from windows array
     */
    public void removeChild(Surface s) {
        this.child.remove(s);
    }
    
    /**
     * 
     * @param tempInside inside temperature in Celcius grades
     * @param tempOutside outside temperature in Celcius grades
     * @return heat loss in W/m^2*K where K is temp inside - temp outside
     */
    @Override
    public double computeHeatLoss(double tempInside, double tempOutside) {
        if(tempOutside < 0) {
            this.tempDifference = tempInside + Math.abs(tempOutside);
        }
        else {
            this.tempDifference = tempInside  - tempOutside;
        }
        return this.computeHeatLoss(tempDifference);//Watt per surface
    }
    
    /**
     * 
     * @param tempDifference between temperature inside and outside in Celcius grades
     * @return 
     */
    @Override
    public double computeHeatLoss(double tempDifference) {
        double result; //W/m^2*K
        this.tempDifference = tempDifference; // Celcius grads
        if(this.child != null && this.child.size() > 0) {
            double winHeatLoss = 0;//transmisjonsvarmetap gjennom vinduer
            for(int i = 0; i < this.child.size(); i++) {
                winHeatLoss += this.child.get(i).computeHeatLoss(this.tempDifference);//summerer varmetap fra alle vinduer
            }
            result = ((this.square - this.countSquareOfChildren())) * this.uValue * this.tempDifference + winHeatLoss;  
        }
        else {
            result = (this.square) * this.uValue * this.tempDifference;
        }
        return result;//Watt         
    }
    
    
    /**
     * 
     * @return total squire of all windows at this surface
     */
    public double countSquareOfChildren() {
        double result= 0;
        if(this.child == null) {
            return 0;
        }
        for(int i = 0; i < this.child.size(); i++) {
            result += this.child.get(i).square;
        }
        return result;
    }
   
    /*************************************************************************/
    /* get og set metoder her */
    
    /**
     * 
     * @return 
     */
    public double getDimX() {
        return dimX;
    }

    /**
     * 
     * @param dimX 
     */
    public void setDimX(double dimX) {
        this.dimX = dimX;
    }

    /**
     * 
     * @return 
     */
    public double getDimY() {
        return dimY;
    }

    /**
     * 
     * @param dimY 
     */
    public void setDimY(double dimY) {
        this.dimY = dimY;
    }

    /**
     * 
     * @return 
     */
    public char getOrientation() {
        return orientation;
    }

    /**
     * 
     * @param orientation 
     */
    public void setOrientation(char orientation) {
        this.orientation = orientation;
    }

    /**
     * 
     * @return 
     */
    public double getSquare() {
        return square;
    }

    /**
     * 
     * @param square 
     */
    public void setSquare(double square) {
        this.square = square;
    }

    /**
     * 
     * @return 
     */
    public double getuValue() {
        return uValue;
    }

    /**
     * 
     * @param uValue 
     */
    public void setuValue(double uValue) {
        this.uValue = uValue;
    }
        
    /***************************************************************************/
    
    @Override
    public String toString() {
        String s = "Surface #"+this.hashCode()+System.getProperty("line.separator");
        s +="dimension x: "+this.dimX+System.getProperty("line.separator");
        s +="dimension y: "+this.dimY+System.getProperty("line.separator");
        s +="U value: "+this.uValue+System.getProperty("line.separator");
        s +="Total square: "+this.square+"m^2"+System.getProperty("line.separator");
        //s +="Windows quantity: "+this.windows.size()+System.getProperty("line.separator");
        //s +="Windows area: "+this.windows.get(0).square;
        return s;
    }
}

